package wikist.controller;

import java.text.MessageFormat;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;

import wikist.model.PageEntry;
import wikist.service.management.page.PageEntryManagementService;
import wikist.service.wikiconverter.WikiConvertService;

/**
 * Wikiページへのリクエストを受け取るコントローラー
 * 
 * @author onjiro.mohyahya
 */
public class PageRequestController extends Controller {

    private Logger logger =
        Logger.getLogger(PageRequestController.class.getName());

    private PageEntryManagementService contentManagement =
        new PageEntryManagementService();

    private WikiConvertService convertService = new WikiConvertService();

    @Override
    public Navigation run() throws Exception {
        String pagepath = (String) this.request.getAttribute("page");

        logger.entering(this.getClass().getName(), "run");
        logger.info(MessageFormat.format(
            "following URL is requested. Method={0} PageURL={1}",
            this.request.getMethod(),
            pagepath));

        try {
            if (this.isGet()) {
                return this.request(pagepath);
            } else if (this.isPost()) {
                return this.entry(this.gatherEntryRequestFrom(this.request));
            } else {
                throw new IllegalArgumentException();
            }
        } finally {
            logger.exiting(this.getClass().getName(), "run");
        }
    }

    /**
     * ページエントリー情報をリクエストから収集します
     * 
     * @param req
     *            リクエスト
     * @return ページエントリー情報
     */
    private PageEntry gatherEntryRequestFrom(HttpServletRequest req) {
        PageEntry entryInformation = new PageEntry();
        entryInformation.setUrl((String) req.getAttribute("page"));
        entryInformation.setTitle((String) req.getAttribute("title"));
        entryInformation.setContentInWiki((String) req.getAttribute("content"));
        return entryInformation;
    }

    /**
     * ページ情報の登録をリクエストされた場合のページ遷移を行ないます。
     * <p>
     * 該当の場合、ページ情報を登録し、登録されたページを表示します。
     * </p>
     * 
     * @param entry
     *            登録情報
     * @return 登録された内容を表示するページへの遷移ナビゲーション
     */
    private Navigation entry(PageEntry entry) {
        // ページ情報の登録
        this.contentManagement.entry(entry.getUrl(), entry.getTitle(), entry
            .getContentInWiki());

        // 登録したページ情報の取得
        PageEntry requestEntry =
            this.contentManagement.get(entry.getUrl());
        String contentInHtml =
            this.convertService.convert(requestEntry.getContentInWiki());
        this.request.setAttribute("url", requestEntry.getUrl());
        this.request.setAttribute("title", requestEntry.getTitle());
        this.request.setAttribute("content", contentInHtml);
        return this.forward("view.jsp");
    }

    /**
     * ページ内容の表示をリクエストされた場合のページ遷移を行ないます。
     * <p>
     * 該当の場合、指定されたURLに対応するするページが登録されていれば、それを表示します。
     * 対応するページが登録されていない場合は新規にページ内容を登録するページを表示します。
     * </p>
     * 
     * @param url
     *            リクエスト対象URL
     * @return ペーイの登録がある場合、登録された内容を表示するページへの遷移ナビゲーション。ない場合、新規登録ページへの遷移ナビゲーション
     */
    private Navigation request(String url) {
        PageEntry entry = this.contentManagement.get(url);
        logger.info(MessageFormat.format(
            "requested URL={0} {1}",
            url,
            (entry == null) ? "not exists." : "already exists."));

        Navigation forwardPage = this.forward("view.jsp");
        if (entry == null) {
            entry = new PageEntry();
            entry.setUrl(url);
            forwardPage = this.forward("new.jsp");
        }

        String contentInHtml =
            (entry.getContentInWiki() == null) ? "" : this.convertService
                .convert(entry.getContentInWiki());
        this.request.setAttribute("url", entry.getUrl());
        this.request.setAttribute("title", entry.getTitle());
        this.request.setAttribute("content", contentInHtml);
        return forwardPage;
    }

}
